package com.jt.service.impl;

import com.jt.service.FileService;
import com.jt.vo.ImageVO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

/**
 * 反向代理
 *  特点：
 *      1、反向代理是位于用户和目标服务器之间的
 *      2、用户以为反向代理服务器就是真实的服务器，用户不知道真实的服务器地址
 *      3、反向代理服务器保护服务端信息，称为服务器端代理
 *
 * 正向代理
 *  特点：
 *      1、代理服务器位于用户与服务器之间
 *      2、用户在请求时，非常明确真实服务器地址，服务器不清楚访问的用户是谁
 *      3、正向代理服务器保护用户信息，称为客户端代理
 */
@Service
@PropertySource(value = "classpath:/properties/image.properties",encoding = "UTF-8")//将配置文件导入容器
public class FileServiceImpl implements FileService {
    @Value("${image.fileDir}")
    private String fileDir; //获取根路径
    @Value("${image.urlPath}")
    private String urlpPath; //设置域名地址

    //设置文件类型
    private static Set<String> typeSet= new HashSet<>();
    static{
        typeSet.add(".jpg");
        typeSet.add(".png");
        typeSet.add(".gif");
    }
    /**
     * 实现文件上传
     * 步骤：
     *      1、校验文件类型
     *      2、校验文件是否为恶意程序
     *      3、采用分目录的结构进行存储
     *      4、避免重名 UUID
     *
     * @param uploadFile
     * @return
     */
    @Override
    public ImageVO upload(MultipartFile uploadFile) {
        /* 1、校验文件类型 */
            //1.1获取文件名称
            String fileName = uploadFile.getOriginalFilename();
            //1.2全部转小写
            fileName = fileName.toLowerCase();
            //1.3获取文件类型
            int index = fileName.lastIndexOf(".");
            String fileType = fileName.substring(index);
            //1.4判断是否是指定类型
            if(!typeSet.contains(fileType)){
                return ImageVO.fail();
            }
        /*2、校验文件是否为图片，高度/宽度*/
            //2.1将数据转化为图片对象
            try {
                // Image I/O API 的主要包。使用 ImageIO 类的静态方法可以执行许多常见的图像 I/O 操作。
                BufferedImage bufferedImage = ImageIO.read(uploadFile.getInputStream());
                int width = bufferedImage.getWidth();
                int height = bufferedImage.getHeight();
                if(width==0 || height==0){
                    return ImageVO.fail();//报错返回
                }
        /*3、采用分目录的结构进行存储*/
            //3.1设置根目录（）
//            String fileDir  = "D:/360/images";
            //3.2按照/yyyy/MM/dd/的方式进行目录划分
            String dataDir = new SimpleDateFormat("/yyyy/MM/dd/")
                                    .format(new Date());
            //3.3拼接文件路径 D:/360/images/yyyy/MM/dd
            String fileDirPath = fileDir+dataDir;
            //3.4 判断目录是否存在，不存在则创建目录
            File dirFile = new File(fileDirPath);
            if(!dirFile.exists()){
                dirFile.mkdirs();
            }
        /*4、避免重名 UUID*/
            //4.1准备文件名
            String uuid = UUID.randomUUID()
                    .toString().replace("-", "");
            //4.2动态生成文件名称 uuid.jpg
            String uuidName = uuid+fileType;
            //4.3实现文件上传 D:/360/images/yyyy/MM/dd/uuid.jpg
            File realFile = new File(fileDirPath+uuidName);
            uploadFile.transferTo(realFile);
            //
            String url = urlpPath+dataDir+uuidName;
            return ImageVO.success(url, width, height);

            }catch (IOException e){
                e.printStackTrace();
                return ImageVO.fail();//报错返回
            }
    }
}
